
import 'package:flutter/material.dart';
import 'package:jpush_flutter/jpush_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
import './utils/login.dart' show Login;
import 'models/search_arguments.dart';
import 'models/detail_arguments.dart';
import 'models/member_model.dart';
import 'models/siteinfo_model.dart';
import 'utils/request.dart';
import 'utils/toast.dart';

import 'pages/swipe.dart';
import 'pages/home/home.dart';
import 'pages/product/index.dart' as product;
import 'pages/product/detail.dart' as product;
import 'pages/product/list.dart' as product;
import 'pages/article/index.dart' as article;
import 'pages/article/detail.dart' as article;
import 'pages/article/list.dart' as article;
import 'pages/about/index.dart' as about;

class Application{
  static Login login;
  static SharedPreferences spref;
  static bool isConnected = false;

  static Map<String,dynamic> pageCaches = new Map();

  static ValueNotifier<MemberModel> memberNotify;
  static Request member;
  static ValueNotifier<SiteinfoModel> siteinfoNotify;
  static Request siteinfo;
  static ValueNotifier<int> cartCountNotify;
  static ValueNotifier<bool> isLoginNotify;

  static ValueNotifier<String> rootRouteNotify;
  static Map<String, WidgetBuilder> routes;
  static Map<String, String> redirects;

  static BuildContext _context ;

  static JPush jPush;
  static String regId;

  static bool initialized = false;

  static init() async{
    if(initialized )return;
    initialized = true;

    routes = {
      '/home': (context) => HomePage(),
      '/swipe': (context) => SwipePage(),
      '/product': (context) => product.IndexPage(),
      '/product/list': (context) => product.ListPage(arguments:SearchArguments.fromObject(ModalRoute.of(context).settings.arguments)),
      '/product/detail': (context) => product.DetailPage( arguments:DetailArguments.fromObject(ModalRoute.of(context).settings.arguments) ),
      '/article': (context) => article.IndexPage(),
      '/article/list': (context) => article.ListPage(arguments:SearchArguments.fromObject(ModalRoute.of(context).settings.arguments)),
      '/article/detail': (context) => article.DetailPage(arguments:DetailArguments.fromObject(ModalRoute.of(context).settings.arguments)),
      '/about': (context) => about.IndexPage(),
    };
    redirects = {};

    spref =await SharedPreferences.getInstance();

    login = new Login();

    member = new Request('member/profile');

    siteinfo = new Request('common/siteinfo');

    cartCountNotify = ValueNotifier(0);
    cartCountNotify.addListener((){
      print('cart count changed:'+cartCountNotify.value.toString());
    });

    memberNotify = ValueNotifier(MemberModel());
    memberNotify.addListener((){
      print('member info changed:'+memberNotify.value.id.toString());
    });

    siteinfoNotify = ValueNotifier(SiteinfoModel());
    siteinfoNotify.addListener((){
      print('site info changed');
    });

    rootRouteNotify = ValueNotifier('');
    rootRouteNotify.addListener((){
      print('root tab changed:'+rootRouteNotify.value);
    });

    await login.restoreToken();

    startJPush();
  }

  static dispose() {
    if(!initialized)return;
    _context = null;

    siteinfoNotify.dispose();
    siteinfoNotify = null;
    memberNotify.dispose();
    memberNotify = null;
    cartCountNotify.dispose();
    isLoginNotify.dispose();

    pageCaches.clear();

    spref = null;

    initialized = false;
  }

  static getContext() {
    return _context;
  }
  static setContext(context) {
    print(context);
    _context = context;
  }

  static toast(message,[duration = 2]){
    Toast.show(message,duration: duration);
  }

  static Future<SiteinfoModel> getSiteinfo({force = false}) async {
    if(!force && siteinfoNotify.value.name.isNotEmpty){
      return Future.value(siteinfoNotify.value);
    }
    var sJson = await siteinfo.getData(force:force);
    siteinfoNotify.value = SiteinfoModel.fromJson(sJson);
    return siteinfoNotify.value;
  }

  static Future<MemberModel> getProfile({force = false}) async {
    if(!force && memberNotify.value.id > 0){
      return Future.value(memberNotify.value);
    }
    var mJson = await member.getData(force:force);
    memberNotify.value = MemberModel.fromJson(mJson);
    return memberNotify.value;
  }

  static cachePage(String name, dynamic data){
    pageCaches[name]=data;
  }
  static getPage(String name){
    return pageCaches.containsKey(name)?
      pageCaches[name]:null;
  }

  static back(BuildContext context){
    if(Navigator.canPop(context)){
      Navigator.pop(context);
    }else{
      Navigator.pushReplacementNamed(context, '/');
    }
  }
  static route(String url, {Map<String,dynamic> arguments}){
    if(url == null){
      return;
    }
    if(url.indexOf('/pages/') == 0){
      url = url.substring(6);
    }
    if(arguments == null) arguments=Map();
    if(url.indexOf('?') > 0){
      List<String> parts= url.split('?');
      url = parts[0];
      List<String> query = parts[1].split('&');
      query.forEach((item){
        int idx = item.indexOf('=');
        if(idx>0){
          arguments[item.substring(0,idx)] = item.substring(idx+1);
        }
      });
    }
    //不在路由范围内再尝试去除尾部 index
    if(!routes.containsKey(url) && !redirects.containsKey(url)) {
      if (url.endsWith('/index')) {
        url = url.substring(0, url.length - 6);
      }
    }
    print(['Navigate '+url,arguments]);
    if(redirects.containsKey(url)){
      print('route redirect:'+url);
      route(redirects[url], arguments:arguments);
      return;
    }
    
    if(!routes.containsKey(url)){
      Toast.show('页面不存在');
      return;
    }

    if(url == '/'){
      Navigator.popUntil(_context, (route)=> route.settings.name == '/', );
      print(['tab:',arguments['route']]);
      //确保每次都通知到
      rootRouteNotify.value = arguments['route'].toString() + '?'+DateTime.now().millisecondsSinceEpoch.toString();
    }else {
      Navigator.pushNamed(_context, url, arguments: arguments);
    }
  }

  static startJPush() async{
    jPush = new JPush();
    jPush.addEventHandler(
      // 接收通知回调方法。
      onReceiveNotification: (Map<String, dynamic> message) async {
        print("flutter onReceiveNotification: $message");
      },
      // 点击通知回调方法。
      onOpenNotification: (Map<String, dynamic> message) async {
        print("flutter onOpenNotification: $message");
      },
      // 接收自定义消息回调方法。
      onReceiveMessage: (Map<String, dynamic> message) async {
        print("flutter onReceiveMessage: $message");
      },
    );
    jPush.setup(
      appKey: "62eb07d227d1f11dd7fa6239",
      channel: "developer-default",
      production: false,
      debug: true, // 设置是否打印 debug 日志
    );
    jPush.getRegistrationID().then((rid) {
      regId = rid;
      print('get registrationid: '+ rid);
    });
  }
}